home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * XPrint.c. C code for a printer driver for daisy-wheel printers
- * for the Macintosh.
- * Earle R. Horton. August 17, 1987
- * LightspeedC source.
- * Set the project type to Device Driver, ID #2.
- * Run RMaker to put the resources in the printer resource file.
- * Install with Chooser.
- */
- #include <WindowMgr.h> /* includes QuickDraw.h, MacTypes.h */
- #include <EventMgr.h>
- #include <DialogMgr.h>
- #include <SerialDvr.h>
- #include <FontMgr.h>
- #include <HFS.h>
- #include <asm.h>
- #define DRIVER_MODULE
- #include "prglobals.h"
- /*
- * LightspeedC doesn't provide these as InLines. To save space, I provide
- * my own routines. This way, I get around having to link in MacTraps.
- */
- int HNoPurge();
- int HPurge();
- int HLock();
- int CloseDriver();
-
- int checkabort();
-
- /* Useful constants */
- #define OPEN 0
- #define PRIME 1
- #define CONTROL 2
- #define STATUS 3
- #define CLOSE 4
-
-
- #define SERRESET 8
- #define SERSHAKE 10
-
-
- #define XONCR ((char)17)
- #define XOFFCR ((char)19)
- #define RESFILEID (-8192)
- #define PACKID (-4080)
-
- main(p, d, n)
- PrParam *p; /* ==> parameter block */
- DCtlPtr d; /* ==> device control entry */
- int n; /* entry point selector */
-
- {
- /* Check to make sure our data area was allocated. It may not have been
- * if we were opened with a low-level open or even a device manager PBOpen()
- * and our printer resource file was not opened. Note that we cannot use
- * any of LightspeedC's "global" variables until after we get our storage
- * from the resource file and lock it down, making A4 point to it. This
- * probably does the same thing that the prolog code attempts to do with
- * the original 'DATA' resource created by LightspeedC.
- */
- int i;
- Handle storage;
- if(d->dCtlStorage == nil && n != CLOSE){
- if (openprinterfile(d) == -1){
- PrintErr = ResError();
- CloseDriver(d->dCtlRefNum);
- return(-1);
- }
- }
- HLock(d->dCtlStorage);
- storage = d->dCtlStorage;
- asm{
- movea.l storage,a0 ;; LightspeedC uses A4 as the base
- movea.l (a0),a4 ;; for driver globals.
- }
- if (d->dCtlStorage != nil) switch (n){ /* dispatch */
-
- case OPEN: /* open */
- openprinterfile(d);
- if((settings = (Pfg)(GetResource('Stng',RESFILEID))) == nil ||
- GetResource('STR#',PACKID) == nil){
- CloseDriver(d->dCtlRefNum);
- return(-1); /* Can't run without these. */
- }
- LoadResource(settings);
- HNoPurge(settings);
- SetControlStrings();
- SPopen();
- HPurge(settings);
- settings = nil;
- prpb.ioNamePtr = prname;
- break;
-
- case PRIME: /* For read/write calls, not applicable here. */
- break;
-
- case CONTROL: /* control */
- switch (p->csCode){ /* Device Control Call */
- /* p->csCode gives opcode, and we switch on */
- /* it to perform low-level Printing calls */
- case iPrBitsCtl: /* Send a bitmap to the printer (NA). */
- break;
- case iPrIOCtl: /* Text streaming. */
- iopb.ioParam.ioBuffer = (Ptr)p->lParam1;
- iopb.ioParam.ioReqCount = p->lParam2;
- asm{
- lea iopb,a0
- PBWrite
- }
- break;
- case iPrEvtCtl: /* Screen printing. (cmd-shift 4, NA.)*/
- break;
- case iPrDevCtl: /* CR, LF, FF, etc. */
- devicecontrol(p->lParam1);
- break;
- case iFMgrCtl:
- /* Font manager font table modify request. p->lParam1 is a pointer to
- * an FMInput record. (IM says we get an FMOutPtr here, but MacsBug says
- * we get a pointer to an FMInput. I go with MacsBug.) In addition, the
- * integer following p->lParam1 contains our driver reference number and
- * a private byte we can use internally.
- * The application first does something to determine the characteristics of
- * fonts in our printing GrafPort. The Font Manager calls our status
- * routine with csParam = 8 and we give it a "font characterization table".
- * The Font Manager selects a font, and calls our control routine to confirm
- * the choice. We change it to Monaco 9, horizontal scaling. If you need to
- * support proportional fonts, then you have to do something about it here
- * and in the printing code, too. Good luck.
- */
- {
- FMInput *fontset;
- fontset = (FMInput *)p->lParam1;
- fontset->family = monaco;
- fontset->face = 0;
- fontset->needBits = 0;
- fontset->numer = noscale;
- fontset->denom = noscale;
- if(fontset->device == IDEV10){
- fontset->size = 10;
- fontset->numer.h = 7;
- fontset->denom.h = 6;
- }
- else if(fontset->device == IDEV15){
- fontset->size = 7;
- fontset->numer.h = 5;
- fontset->denom.h = 6;
- }
- else fontset->size = 9;
- }
- break;
- default:
- break;
- }
- break;
- case STATUS:
- switch (p->csCode){ /* Device Status Call */
- /* p->csCode gives opcode, and we switch on */
- /* it to perform low-level Printing calls */
- case iFMgrCtl:
- /* Font manager font table request. Help out the Font Manager.
- /* p->lParam1 is a pointer to an area in memory in which to put a copy
- * of the information describing our font capabilities. p->lParam2 has
- * an integer in its high order word which contains the "resolution" to use,
- * set in a style dialog with the user. We say we have different horizontal
- * resolutions, based on the number of characters per inch used. I believe
- * this gets called whenever the application does a GetFontInfo() or
- * StringWidth() or whatever for the first time in one of our printing
- * GrafPorts. Possibly also when the application tries to change the
- * font style.
- */
- *((fontab *)p->lParam1) = myfonts;
- break;
- default:
- break;
- }
- break;
- case CLOSE: /* close */
- if(storage != nil){
- HPurge(storage);
- d->dCtlStorage = nil;
- }
- break;
- }
-
- /* done */
-
- return(0);
- }
- SPopen() /* Open the serial driver and configure it. */
- /* Use low-level ROM routines. */
- {
- ParmBlkPtr pb;
- int serconfig;
- pb = &iopb;
- switch (pport){ /* get the correct port */
- case 0: /* modem port */
- if(!phone) {
- prinit("\p.AOut");
- phone = TRUE;
- }
- drivernum = AoutRefNum;
- break;
- case 1: /* printer port */
- if(!printer) {
- prinit("\p.BOut");
- printer = TRUE;
- }
- drivernum = BoutRefNum;
- break;
- }
- /* set up the io parameter block for writing to the serial driver. */
- /* a control call resets the baud rate */
- pb->ioParam.ioRefNum = drivernum;
- pb->ioParam.ioCompletion = nil;
- ((cntrlParam *)pb)->csCode = SERRESET;
- serconfig = data8 + noParity + stop20;
- serconfig += mybauds[pbaud].rate;
- ((cntrlParam*)pb)->csParam[0] = serconfig;
- asm{
- move.l pb,a0
- PBControl
- }
- #define shake ((SerShk*)&((cntrlParam*)pb)->csParam[0])
- shake->errs = FALSE;
- shake->evts = FALSE;
- shake->fDTR = FALSE;
- shake->fInX = FALSE;
- if(XonXoff && (theWorld.machineType >= envMachUnknown)){
- shake->fXOn = TRUE;
- shake->fCTS = FALSE;
- shake->xOn = XONCR;
- shake->xOff = XOFFCR;
- }
- else {
- shake->fXOn = FALSE;
- shake->fCTS = TRUE;
- }
- ((cntrlParam *)pb)->csCode = SERSHAKE;
- asm{
- move.l pb,a0
- PBControl
- }
-
- #undef shake
- pb->ioParam.ioPosMode = 0;
- pb->ioParam.ioPosOffset = 0;
- }
-
- prinit(name) /* Open a driver by name. */
- StringPtr name; /* ROM serial driver? RAM serial driver? Who cares? */
- {
- iopb.ioParam.ioNamePtr = name;
- iopb.ioParam.ioCompletion = nil;
- iopb.ioParam.ioPermssn = 0;
- asm{
- lea iopb,a0
- PBOpen
- }
- }
- /*
- * Set the printer control strings based on what is in our STR# resource.
- */
- SetControlStrings()
- {
- unsigned char *strptr;
- unsigned char **mystrings;
-
- mystrings = (unsigned char **)GetResource('STR#',PACKID);
- if(mystrings != nil){
- LoadResource(mystrings);
- copystr( (strptr = (*mystrings)+2) , prlfstr);
- copystr( (strptr += (*strptr) + 1) , prinitstr);
- copystr( (strptr += (*strptr) + 1) , prtopstr);
- copystr( (strptr += (*strptr) + 1) , preopstr);
- copystr( (strptr += (*strptr) + 1) , preofstr);
- decode(prlfstr);
- decode(prinitstr);
- decode(prtopstr);
- decode(preopstr);
- decode(preofstr);
- }
- }
- decode(str)
- unsigned char *str;
- {
- register unsigned char i,count;
- count = 1;
- for(i=0;str[0]-i++;){
- if (str[i] == '^') str[count] = 31 & str[++i];
- else str[count] = str[i];
- count++;
- }
- str[0] = count - 1;
- }
- /*
- * This is for copying PASCAL strings. Simple.
- */
- copystr(src,dst)
- unsigned char *src,*dst;
- {
- asm{
- clr.l d0
- move.l src,a0
- move.l dst,a1
- move.b (a0),d0
- loop:
- move.b (a0)+,(a1)+
- dbra d0,@loop
- }
- }
- devicecontrol(code) /* Handle printer device control calls. */
- long code;
- {
- switch(code){
- case lPrReset:
- printstring(prinitstr);
- break;
- case lPrPageEnd:
- printstring(preopstr);
- break;
- case lPrLineFeed:
- case lPrLFSixth:
- case lPrLFEighth:
- printstring(prlfstr);
- break;
- default: /* Unknown parameter. */
- break;
- }
- }
- printstring(string) /* Send a printer control string to the */
- /* serial driver. */
- unsigned char *string;
- {
- iopb.ioParam.ioBuffer = (Ptr)(string+1);
- iopb.ioParam.ioReqCount = (long)(string[0]);
- asm{
- lea iopb,a0
- PBWrite
- }
- }
- /* Find the system folder, and open our printer resource file, if we can.
- * Fill in a global SysEnvRec, which might be useful for other stuff.
- */
- int openprinterfile(d)
- DCtlPtr d;
- {
- SysEnvRec myWorld;
- StringHandle ourname;
- int therefnum;
- Handle storage;
-
- if(d->dCtlStorage != nil)
- HPurge(d->dCtlStorage);
- ourname = (StringHandle)GetResource('STR ',0xE000);
- LoadResource(ourname);
- HNoPurge(ourname); /* Get printer resource file name. */
- HLock(ourname);
- SysEnvirons(1,&myWorld);
- if(myWorld.machineType >= envMachUnknown)
- therefnum = OpenRFPerm(*ourname,myWorld.sysVRefNum,fsCurPerm);
- else
- therefnum = OpenResFile(*ourname);
- HPurge(ourname);
- if (therefnum != -1){
- d->dCtlStorage = (Handle)GetResource('PREC',RESFILEID);
- if(d->dCtlStorage != nil){
- LoadResource(d->dCtlStorage);
- DetachResource(d->dCtlStorage);
- HNoPurge(d->dCtlStorage);
- HLock(d->dCtlStorage);
- storage = d->dCtlStorage;
- asm{
- movea.l storage,a0 ;; LightspeedC uses A4
- movea.l (a0),a4 ;; for driver globals.
- }
- theWorld = myWorld;
- }
- }
- return (therefnum);
- }
- int HNoPurge(c)
- char *c;
- {
- asm{
- move.l c,a0
- HNoPurge
- }
- }
- int HPurge(c)
- char *c;
- {
- asm{
- move.l c,a0
- HPurge
- }
- }
- int HLock(c)
- char *c;
- {
- asm{
- move.l c,a0
- HLock
- }
- }
- int CloseDriver(refnum)
- int refnum;
- {
- ParamBlockRec closepb;
- asm{
- lea closepb,a0
- move.w refnum,24(a0)
- clr.l 12(a0)
- PBClose
- move.w 16(a0),d0
- }
- }
-